<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>总结Vue数据监测</title>
  <script src="../js/vue.js"></script>
</head>
<body>
  <!-- 
    Vue侦听数据的原理：
      1. vue会监视data中所有层次的数据。
      2. 如何检测对象中的数据？
        通过setter实现监听，且要在new Vue时就传入要检测的数据。
        (1).对象中后追加的属性，Vue默认不做响应式处理
        (2).如果需要给后添加的属性做响应式，请使用如下API：
          Vue.set(target, propertyName/index, value) 或
          vm.$set(target, propertyName/index, value)
      3. 如何检测数组中数据？
        通过包裹数组更新元素的方法实现，本质就是做了两件事：
        (1).调用原生对应的方法对数组进行更新。
        (2).重新解析模板，进而更新页面。
      4. 在Vue修改数组中的某个元素一定要用如下方法：
        1. 使用这些API（7个，改变原数组）:push()、pop()、shift()、unshift()、splice()、sort()、reverse()；变更方法，顾名思义，会变更调用了这些方法的原始数组。相比之下，也有非变更方法，例如 filter()、concat() 和 slice()。它们不会变更原始数组，而总是返回一个新数组。当使用非变更方法时，可以用新数组替换旧数组：
        2. Vue.set()或vm.$set()   $delete()

      特别注意：Vue.set()或vm.$set()不能给vm或vm的根数据对象添加属性！！！
   -->
  <div id="root">
    <h1>学生信息</h1>

    <button @click="student.age++">年龄+1岁</button> <br/>
    <button @click="addSex">添加一个性别属性，默认值：男</button> <br/>
    <button @click="student.sex = '未知'">修改性别</button> <br/>
    <button @click="addFriends">在列表首位添加一个朋友</button> <br/>
    <button @click="updateFirstFriend">修改第一个朋友的名字为：张三</button> <br/>
    <button @click="addHobby">添加一个爱好</button> <br/>
    <button @click="updateFirstHobby">修改第一个爱好为：开车</button> <br/>
    <button @click="removeSmoke">过滤掉爱好中的抽烟</button>

    <h2>姓名：{{student.name}}</h2>
    <h2 v-if="student.sex">性别：{{student.sex}}</h2>  
    <!-- {{student.sex}} sex没有定义，这里是不报错的，会不显示因为没有是undefined，undefined不会显示出来；
    如果未定义，vm._data.student.sex 手动添加并赋值，页面也不会显示出来 -->
    <h2>年龄：{{student.age}}</h2>
    <h2>爱好</h2>
    <ul>
      <li v-for="(f, index) in student.friends" :key="index">
        {{f.name}} -- {{f.age}}
      </li>
    </ul>
    <h2>朋友们</h2>
    <ul>
      <li v-for="(h, index) in student.hobby" :key="index">
        {{h}}
      </li>
    </ul>
  </div>
  <script>
    Vue.config.productionTip = false; // 阻止vue在启动时生成生产提示。
    const vm = new Vue({
      el: "#root",
      data: {
        student: {
          name: 'Tom',
          age: 18,
          hobby: ['喝酒','抽烟','烫头'],
          friends: [
            {name: 'Jerry', age: 31},
            {name: 'Tony', age: 32}
          ]
        }
      },
      methods: {
        addSex() {
          Vue.set(this.student, 'sex', '男')
          // this.$set(this.student, 'sex', '男')
        },
        addFriends() {
          this.student.friends.unshift({name: 'Jack', age: 31})
        },
        updateFirstFriend() {
          this.student.friends[0].name = '张三'
        },
        addHobby() {
          this.student.hobby.push('学习')
        },
        updateFirstHobby() {
          // this.student.hobby.splice(0, 1, '开车')
          // Vue.set(this.student.hobby, 0, '开车')
          this.$set(this.student.hobby, 0, '开车')
        },
        removeSmoke() {
          this.student.hobby = this.student.hobby.filter(h => {
            return h !== '抽烟'
          })
        }
      },
    })
  </script>
</body>
</html>